<?php
// +----------------------------------------------------------------------
// | Description: 解决跨域问题
// +----------------------------------------------------------------------
// | Author: orchief
// +----------------------------------------------------------------------

namespace App\Common\Controller;
use EasySwoole\Core\Http\AbstractInterface\REST;
use EasySwoole\Config;
use \Firebase\JWT\JWT;
use \EasySwoole\Core\Http\Request;
use \EasySwoole\Core\Http\Response;
use think\Cache;
use App\Utility\Extend\AuthAdapter;
use think\Db;
use App\Utility\Traits\JsonReturn;

class Common extends REST
{
    use JsonReturn;
    public $modelName = '';   // model 类名称
    public $param;
    static public $model;
    public $whiteList = [
        'GET' => [
            '/Admin/Verify/Index',
            '/Admin/Configs/Index',
        ],
        'PUT' => [
        ],
        'POST' => [
            '/Admin/MemberStatus/Index',
            '/Admin/Members/Index',
            '/upload'
        ]
    ];

    /**
     * 请求前置动作
     */
    protected function onRequest($action):?bool
    {
        // 接受参数
        $this->param  = $this->request()->getRequestParam();
        try{
            $JsonParam = json_decode($this->request()->getBody()->__toString(), true);
            if(is_array($JsonParam)){
                $this->param = $this->param + $JsonParam;
            }
        }catch(\Exception $e){

        }

        $this->header = $this->request()->getHeaders();
        
        // 白名单
        if($this -> checkWhiteList()){
            
            return true;
        }
        
         $instance = Config::getInstance();
         try{
            $res = $this->cms();
            
        }catch(\Exception $e){
            var_dump($e->getMessage());
            if($instance->getConf('DEBUG')){
                return true;
            }else{
                return $res;
            }
        }

        if($instance->getConf('DEBUG')){
            return true;
        }else{
            return $res;
        }
        
        return $this->cms();
    }

    /**
     * 白名单检验
     */
    public function checkWhiteList()
    {
        $path = $this->request()->getUri()->getPath();
        $method = $this->request()->getMethod();
        return isset($this->whiteList[$method]) && in_array($path, $this->whiteList[$method]);
    }

    public function expire($decoded)
    {
        $this->abort($decoded->expireDate > time(), ['msg' => '登录失效！']);
    }

    public function cms()
    {
        $this->abort(isset($this->header['authorization']), ['msg' => '鉴权失败1', 'code' => 403]);
        $instance = Config::getInstance();
        $key = $instance->getConf('jwt.key');
        try {
            $decoded = JWT::decode($this->header['authorization'][0], $key, array('HS256'));
        } catch (\Exception $e) {
            $this->abort(false, ['msg' => '鉴权失败2!', 'code' => 403]);
        }

        $this->expire($decoded);
        $this->abort(isset($decoded->userId), ['msg' => '鉴权失败3!', 'code' => 403]);
        $this->abort(isset($decoded->authlist), ['msg' => '鉴权失败4!', 'code' => 403]);
        $this->param['userId'] = $decoded->userId;
        $this->param['adminId'] = $decoded->adminId;
        $this->role = $decoded->role;
        $authlist = $decoded->authlist;

        $authAdapter = new AuthAdapter($authlist);
        $path = $this->request()->getUri()->getPath();
        $method = $this->request()->getMethod();
        $arrPath = explode('/', $path);
        
        switch($method){
            case 'GET': 
            $action = 'index';
            break;
            case 'POST': 
            $action = 'save';
            break;
            case 'PUT':
            $action = 'update';
            break;
            case 'DELETE': 
            $action = 'delete';
            break;
        }
        $ruleName = $arrPath[1].'-'.$arrPath[2].'-'.$action;
        $ruleName = strtolower($ruleName);

        $this->abort($authAdapter->checkLogin($ruleName, $this->param['adminId'], $this->role), ['msg' => '权限不足', 'code' => 103]);

        // 检查改用户是否被拉黑
        $res = Db::table('admin_user') -> where(['id' => $this->param['adminId'], 'status' => 1]) -> find();
        $this->abort($res, ['msg' => '账户被冻结', 'code' => 101]);
        $this->isClient = true; // 权限验证通过 标注该访问为客户端

        return true;
    }

    protected function actionNotFound($action): void
    {
        $a = $this->request()->getMethod();
        $res = json_encode(['code' => 404, 'msg' => '路径/方法错误'], JSON_UNESCAPED_UNICODE);
        $this->response()->withStatus(200);
        $this->response()->write($res);
    }

    /**
     * 实例化model
     */
    protected function model($modelName=null)
    {
        $ModelPath = isset($modelName) ? 'App\\Model\\'.$modelName : 'App\\Model\\'.$this->modelName;
        self::$model = new $ModelPath();
        return self::$model;
    }

    /**
     * 数据检查
     *
     * @param array $rules      检验规则
     * @param array $message    自定义异常消息
     * @param array $data       被检验数据
     * @return void
     */
    public function validate($data, $rules, $message = [])
    {
        $validate = new \think\Validate($rules, $message);
        $this->abort($validate->check($data), ['msg' => $validate->getError()]);
    }
}
